#include "database.h"

int count = 0; // 用来统计有多少客户端连接，有时候也会作为下标使用
#define MAX_EVENT 3000

sqlite3 *pDB = NULL; // 数据库的指针

void saveChatRecordToFile(SINGLE_CHAT *pIn) // 把聊天记录保存到文件中
{
     char sql[256];
     sprintf(sql, "INSERT INTO messages(sender_name,receiver_name,game_id,message,status) VALUES ('%s','%s',%d,'%s',%d);", pIn->selfName, pIn->destName, pIn->game_id, pIn->text, pIn->status);
     execSql(pDB, sql);
}

void singleChat_func(int sID, MSG msg_g) // 单聊函数
{
     SINGLE_CHAT *pSC = (SINGLE_CHAT *)msg_g.buf;
     LOG sc;
     char sql_1[256];
     sprintf(sql_1, "UPDATE user_logins SET status = 1 WHERE username = '%s';", pSC->selfName);
     execSql(pDB, sql_1);

     QUREY_RST qr;
     char sql[512];
     sprintf(sql, "SELECT * FROM user_logins WHERE username = '%s';", pSC->destName);
     querySql(pDB, sql, &qr);

     if (qr.row > 0)
     {
          int jump = qr.col;
          for (size_t i = 0; i < qr.row; i++)
          {
               sc.id = atoi(qr.pzResult[jump + i * jump]);         // 唯一id
               strcpy(sc.name, qr.pzResult[jump + i * jump + 1]);  // 内容用户名
               sc.fd = atoi(qr.pzResult[jump + i * jump + 2]);     // 对方套接字
               sc.status = atoi(qr.pzResult[jump + i * jump + 3]); // 用户状态
          }
     }
     else
     {
          pSC->status = 1;
          saveChatRecordToFile(pSC); // 不在线 保存数据
          return;
     }
     if (sc.status == 1)
     {
          pSC->status = 0;
          int ret = send(sc.fd, &msg_g, sizeof(msg_g), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
          saveChatRecordToFile(pSC); // 发送成功，保存数据
          return;
     }
     else
     {
          pSC->status = 1;
          saveChatRecordToFile(pSC); // 不在线 保存数据
          return;
     }
}

void chatquit(int sID, MSG msg_g) // 退出聊天函数
{
     SINGLE_CHAT *pSC = (SINGLE_CHAT *)msg_g.buf;
     char sql_1[256];
     sprintf(sql_1, "UPDATE user_logins SET status = 0 WHERE username = '%s';", pSC->selfName);
     execSql(pDB, sql_1);
}

void querygameRecord_all(int sID) // 查询所有账号，并发给客户端
{
     GAME_AC sc;
     MSG msg;

     QUREY_RST qr;
     char sql[] = "SELECT * FROM game_accounts;";
     querySql(pDB, sql, &qr);

     int jump = qr.col;
     for (size_t i = 0; i < qr.row; i++)
     {
          sc.id = atoi(qr.pzResult[jump + i * jump]);             // 唯一id
          strcpy(sc.name, qr.pzResult[jump + i * jump + 1]);      // 内容用户名
          strcpy(sc.game_name, qr.pzResult[jump + i * jump + 2]); // 游戏名
          strcpy(sc.items, qr.pzResult[jump + i * jump + 3]);     // 游戏道具
          sc.status = atoi(qr.pzResult[jump + i * jump + 4]);     // 发售状态
          strcpy(sc.time, qr.pzResult[jump + i * jump + 5]);      // 发售的时间
          sc.price = atoi(qr.pzResult[jump + i * jump + 6]);      // 发售价格
          msg.type = queryChatRec;                                // 消息类型时查询聊天记录
          memcpy(msg.buf, &sc, sizeof(GAME_AC));
          // 把包含有一条聊天记录的消息发送给客户端
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
               break;
          }
     }
     msg.type = queryOver; // 查询结束
     //  把查询的消息发送给客户端
     int ret = send(sID, &msg, sizeof(msg), 0);
     if (ret == -1)
     {
          printf("发送数据出错了\n");
     }
}

void myaccount_func(int sID, MSG msg_g) // 查看自己的账号信息
{
     RGU sc;
     MSG msg;

     QUREY_RST qr;
     char sql[256];
     sprintf(sql, "SELECT * FROM users WHERE username = '%s';", msg_g.buf);
     querySql(pDB, sql, &qr);

     int jump = qr.col;
     for (size_t i = 0; i < qr.row; i++)
     {
          sc.id = atoi(qr.pzResult[jump + i * jump]);         // 唯一id
          strcpy(sc.name, qr.pzResult[jump + i * jump + 1]);  // 内容用户名
          strcpy(sc.pwd, qr.pzResult[jump + i * jump + 2]);   // 密码
          strcpy(sc.phone, qr.pzResult[jump + i * jump + 3]); // 手机号
          strcpy(sc.date, qr.pzResult[jump + i * jump + 4]);  // 生日
          strcpy(sc.role, qr.pzResult[jump + i * jump + 5]);  // 用户类型
          sc.wallet = atoi(qr.pzResult[jump + i * jump + 6]); // 钱包
          msg.type = queryChatRec;                            // 消息类型时查询聊天记录
          memcpy(msg.buf, &sc, sizeof(GAME_AC));
          // 把包含有一条聊天记录的消息发送给客户端
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
               break;
          }
     }
     msg.type = queryOver; // 查询结束
     //  把查询的消息发送给客户端
     int ret = send(sID, &msg, sizeof(msg), 0);
     if (ret == -1)
     {
          printf("发送数据出错了\n");
     }
}

void querygameRecord_gamename(int sID, MSG msg_g) // 查询游戏名账号，并发给客户端
{
     GAME_AC sc;
     MSG msg;

     QUREY_RST qr;
     char sql[512];
     sprintf(sql, "SELECT * FROM game_accounts WHERE game_name = '%s';", msg_g.buf);
     querySql(pDB, sql, &qr);

     int jump = qr.col;
     for (size_t i = 0; i < qr.row; i++)
     {
          sc.id = atoi(qr.pzResult[jump + i * jump]);             // 唯一id
          strcpy(sc.name, qr.pzResult[jump + i * jump + 1]);      // 内容用户名
          strcpy(sc.game_name, qr.pzResult[jump + i * jump + 2]); // 游戏名
          strcpy(sc.items, qr.pzResult[jump + i * jump + 3]);     // 游戏道具
          sc.status = atoi(qr.pzResult[jump + i * jump + 4]);     // 发售状态
          strcpy(sc.time, qr.pzResult[jump + i * jump + 5]);      // 发售的时间
          sc.price = atoi(qr.pzResult[jump + i * jump + 6]);      // 发售价格
          msg.type = queryChatRec;                                // 消息类型时查询聊天记录
          memcpy(msg.buf, &sc, sizeof(GAME_AC));
          // 把包含有一条聊天记录的消息发送给客户端
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
               break;
          }
     }
     msg.type = queryOver; // 查询结束
     //  把查询的消息发送给客户端
     int ret = send(sID, &msg, sizeof(msg), 0);
     if (ret == -1)
     {
          printf("发送数据出错了\n");
     }
}

void querygameRecord_name(int sID, MSG msg_g) // 查询用户名账号，并发给客户端
{
     GAME_AC sc;
     MSG msg;

     QUREY_RST qr;
     char sql[256];
     sprintf(sql, "SELECT * FROM game_accounts WHERE username = '%s';", msg_g.buf);
     querySql(pDB, sql, &qr);

     int jump = qr.col;
     for (size_t i = 0; i < qr.row; i++)
     {
          sc.id = atoi(qr.pzResult[jump + i * jump]);             // 唯一id
          strcpy(sc.name, qr.pzResult[jump + i * jump + 1]);      // 内容用户名
          strcpy(sc.game_name, qr.pzResult[jump + i * jump + 2]); // 游戏名
          strcpy(sc.items, qr.pzResult[jump + i * jump + 3]);     // 游戏道具
          sc.status = atoi(qr.pzResult[jump + i * jump + 4]);     // 发售状态
          strcpy(sc.time, qr.pzResult[jump + i * jump + 5]);      // 发售的时间
          sc.price = atoi(qr.pzResult[jump + i * jump + 6]);      // 发售价格
          msg.type = queryChatRec;                                // 消息类型时查询聊天记录
          memcpy(msg.buf, &sc, sizeof(GAME_AC));
          // 把包含有一条聊天记录的消息发送给客户端
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
               break;
          }
     }
     msg.type = queryOver; // 查询结束
     //  把查询的消息发送给客户端
     int ret = send(sID, &msg, sizeof(msg), 0);
     if (ret == -1)
     {
          printf("发送数据出错了\n");
     }
}

void leavefunc(int sID, MSG msg_g) // 留言
{
     LEAVE *sc_1 = (LEAVE *)msg_g.buf;
     MSG msg;

     char sql[256];
     sprintf(sql, "INSERT INTO messages_leave (game_account_id, user_name, message_content) VALUES (%d, '%s', '%s');", sc_1->g_id, sc_1->name, sc_1->items);
     execSql(pDB, sql);
     msg.type = ok;
     send(sID, &msg, sizeof(msg), 0);
}

void chatgoumai(int sID, MSG msg_g) // 查询与购买
{
     GAME_AC *sc_1 = (GAME_AC *)msg_g.buf;
     MSG msg;
     GAME_AC sc;
     LEAVE lc;

     QUREY_RST qr;
     QUREY_RST qr_1;
     char sql[512];
     sprintf(sql, "SELECT * FROM game_accounts WHERE account_id = %d;", sc_1->id);
     querySql(pDB, sql, &qr);
     if (qr.row > 0)
     {
          int jump = qr.col;
          for (size_t i = 0; i < qr.row; i++)
          {
               sc.id = atoi(qr.pzResult[jump + i * jump]);             // 唯一id
               strcpy(sc.name, qr.pzResult[jump + i * jump + 1]);      // 内容用户名
               strcpy(sc.game_name, qr.pzResult[jump + i * jump + 2]); // 游戏名
               strcpy(sc.items, qr.pzResult[jump + i * jump + 3]);     // 游戏道具
               sc.status = atoi(qr.pzResult[jump + i * jump + 4]);     // 发售状态
               strcpy(sc.time, qr.pzResult[jump + i * jump + 5]);      // 发售的时间
               sc.price = atoi(qr.pzResult[jump + i * jump + 6]);      // 发售价格
               msg.type = queryChatRec;                                // 消息类型时查询聊天记录
               memcpy(msg.buf, &sc, sizeof(GAME_AC));
               // 把包含有一条聊天记录的消息发送给客户端
               int ret = send(sID, &msg, sizeof(msg), 0);
               if (ret == -1)
               {
                    printf("发送数据出错了\n");
                    break;
               }
          }
     }
     else
     {
          msg.type = mistake;
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
          return;
     }

     sprintf(sql, "SELECT * FROM messages_leave WHERE game_account_id = %d;", sc_1->id);
     querySql(pDB, sql, &qr_1);
     
     int jump = qr_1.col;
     for (size_t i = 0; i < qr_1.row; i++)
     {
          lc.l_id = atoi(qr_1.pzResult[jump + i * jump]);       // 唯一留言id
          lc.g_id = atoi(qr_1.pzResult[jump + i * jump + 1]);   // 留言游戏id
          strcpy(lc.name, qr_1.pzResult[jump + i * jump + 2]);  // 名字
          strcpy(lc.items, qr_1.pzResult[jump + i * jump + 3]); // 留言的内容
          strcpy(lc.time, qr_1.pzResult[jump + i * jump + 4]);  // 留言的时间
          lc.r_id = atoi(qr_1.pzResult[jump + i * jump + 5]);   // 回复第id的留言
          lc.status = atoi(qr_1.pzResult[jump + i * jump + 6]); // 留言的状态
          msg.type = queryChatRec_leave;                      // 消息类型时查询留言
          memcpy(msg.buf, &lc, sizeof(LEAVE));
          // 把包含有一条聊天记录的消息发送给客户端
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
               break;
          }
     }
     
     msg.type = queryOver; // 查询结束
     //  把查询的消息发送给客户端
     int ret = send(sID, &msg, sizeof(msg), 0);
     if (ret == -1)
     {
          printf("发送数据出错了\n");
     }
}

void goumaifunc(int sID, MSG msg_g) // 购买函数
{
     GOUMAI_CHAT *sc_1 = (GOUMAI_CHAT *)msg_g.buf;
     MSG msg;

     char sql[256];
     sprintf(sql, "UPDATE users SET wallet = wallet - %d WHERE username = '%s';", sc_1->price, sc_1->selfName);
     execSql(pDB, sql); // 扣除买家余额
     sprintf(sql, "UPDATE users SET wallet = wallet + %d WHERE username = '%s';", sc_1->price, sc_1->destName);
     execSql(pDB, sql); // 增加卖家余额
     sprintf(sql, "UPDATE game_accounts SET status = 0 WHERE account_id = %d;", sc_1->game_id);
     execSql(pDB, sql); // 下架该账号
     sprintf(sql, "INSERT INTO orders (buyer_name, seller_name, game_id, price) VALUES ('%s', '%s', %d, %d);", sc_1->selfName, sc_1->destName, sc_1->game_id, sc_1->price);
     execSql(pDB, sql);
     msg.type = user_goumaiover;
     //  把查询的消息发送给客户端
     int ret = send(sID, &msg, sizeof(msg), 0);
     if (ret == -1)
     {
          printf("发送数据出错了\n");
     }
}

void examine_func(int sID, MSG msg_g) // 查看未读消息的行数的函数
{
     SINGLE_CHAT sc;
     MSG msg;
     QUREY_RST qr;
     char sql[256];
     sprintf(sql, "SELECT * FROM messages WHERE receiver_name = '%s' AND status = 1 AND message != 'quit';", msg_g.buf);
     querySql(pDB, sql, &qr);

     memcpy(msg.buf, &qr.row, sizeof(int));
     int ret = send(sID, &msg, sizeof(msg), 0);
     if (ret == -1)
     {
          printf("发送数据出错了\n");
     }
}

void examinelook_func(int sID, MSG msg_g) // 查看未读消息的函数
{
     SINGLE_CHAT sc;
     MSG msg;
     QUREY_RST qr;
     char sql[256];
     sprintf(sql, "SELECT * FROM messages WHERE receiver_name = '%s' AND status = 1 AND message != 'quit';", msg_g.buf);
     querySql(pDB, sql, &qr);

     if (qr.row > 0)
     {
          int jump = qr.col;
          for (size_t i = 0; i < qr.row; i++)
          {
               sc.id = atoi(qr.pzResult[jump + i * jump]);            // 唯一id
               strcpy(sc.destName, qr.pzResult[jump + i * jump + 1]); // 发送者名字
               strcpy(sc.selfName, qr.pzResult[jump + i * jump + 2]); // 接受者名字
               sc.game_id = atoi(qr.pzResult[jump + i * jump + 3]);   // 游戏id
               strcpy(sc.text, qr.pzResult[jump + i * jump + 4]);     // 消息
               strcpy(sc.time, qr.pzResult[jump + i * jump + 5]);     // 消息时间
               sc.status = atoi(qr.pzResult[jump + i * jump + 6]);    // 消息状态
               msg.type = queryChatRec;                               // 消息类型时查询聊天记录
               memcpy(msg.buf, &sc, sizeof(SINGLE_CHAT));
               // 把包含有一条聊天记录的消息发送给客户端
               int ret = send(sID, &msg, sizeof(msg), 0);
               if (ret == -1)
               {
                    printf("发送数据出错了\n");
                    break;
               }
          }
          msg.type = queryOver; // 查询结束
          //  把查询的消息发送给客户端
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
          sprintf(sql, "UPDATE messages SET status = 0 WHERE receiver_name = '%s';", msg_g.buf);
          execSql(pDB, sql);
     }
     else
     {
          msg.type = no_news; // 没有消息
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
     }
}

void examinelookall_func(int sID, MSG msg_g) // 查看新消息
{
     SINGLE_CHAT sc;
     SINGLE_CHAT *sc_p = (SINGLE_CHAT *)msg_g.buf;
     MSG msg;
     QUREY_RST qr;
     char sql[256];
     sprintf(sql, "SELECT * FROM messages WHERE ((sender_name = '%s' AND receiver_name = '%s') OR (sender_name = '%s' AND receiver_name = '%s')) AND game_id = %d AND message != 'quit';", sc_p->selfName, sc_p->destName, sc_p->destName, sc_p->selfName, sc_p->game_id);
     querySql(pDB, sql, &qr);

     if (qr.row > 0)
     {
          int jump = qr.col;
          for (size_t i = 0; i < qr.row; i++)
          {
               sc.id = atoi(qr.pzResult[jump + i * jump]);            // 唯一id
               strcpy(sc.destName, qr.pzResult[jump + i * jump + 1]); // 发送者名字
               strcpy(sc.selfName, qr.pzResult[jump + i * jump + 2]); // 接受者名字
               sc.game_id = atoi(qr.pzResult[jump + i * jump + 3]);   // 游戏id
               strcpy(sc.text, qr.pzResult[jump + i * jump + 4]);     // 消息
               strcpy(sc.time, qr.pzResult[jump + i * jump + 5]);     // 消息时间
               sc.status = atoi(qr.pzResult[jump + i * jump + 6]);    // 消息状态
               msg.type = queryChatRec;                               // 消息类型时查询聊天记录
               memcpy(msg.buf, &sc, sizeof(SINGLE_CHAT));
               // 把包含有一条聊天记录的消息发送给客户端
               int ret = send(sID, &msg, sizeof(msg), 0);
               if (ret == -1)
               {
                    printf("发送数据出错了\n");
                    break;
               }
          }
          msg.type = queryOver; // 查询结束
          //  把查询的消息发送给客户端
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
     }
     else
     {
          msg.type = no_news; // 没有消息
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
     }
}

void affirmself(int sID, MSG msg_g)
{
     SINGLE_CHAT *s = (SINGLE_CHAT *)msg_g.buf;
     char sql[256];
     sprintf(sql, "SELECT * FROM game_accounts WHERE username = '%s' AND account_id = %d;", s->selfName, s->game_id);

     MSG msg;
     QUREY_RST qr;
     // 执行查询语句
     querySql(pDB, sql, &qr);
     // 如果结果的行数是>0的，说明数据库中有记录
     if (qr.row > 0)
     {
          msg.type = bodyname; // 是自己的账号
          send(sID, &msg, sizeof(msg), 0);
     }
     else
     {
          msg.type = notbodyname;          // 不是自己的账号
          strcpy(msg.buf, qr.pzResult[1]); // 内容用户名
          send(sID, &msg, sizeof(msg), 0);
     }
}

void shellfunc(int sID, MSG msg_g) // 上架商品函数
{
     GAME_AC *as = (GAME_AC *)msg_g.buf;
     char szSql[256];
     // 把用户名和密码插入到数据表中
     sprintf(szSql, "INSERT INTO game_accounts (username, game_name, items, price)\
               VALUES ( '%s', '%s' ,'%s', '%d')",
             as->name, as->game_name, as->items, as->price);
     MSG msg;
     char *msg_1 = NULL;
     sqlite3_exec(pDB, szSql, 0, 0, &msg_1);
     // 如果msg不为空，说明有错误信息
     if (msg_1 != NULL)
     {
          sprintf(msg.buf, "上架失败：%s", msg_1);
     }
     else
     {
          sprintf(msg.buf, "上架成功");
     }
     int ret = send(sID, &msg, sizeof(msg), 0);
     if (ret == -1)
     {
          printf("发送数据出错了\n");
     }
}

void quitall_s(MSG msg_g) // 把用户从登录表上删除
{
     char sql[256];
     sprintf(sql, "DELETE FROM user_logins WHERE username = '%s';", msg_g.buf);
     execSql(pDB, sql);
}

void orderfunc(int sID, MSG msg_g) // 订单函数
{
     GOUMAI_CHAT sc;
     MSG msg;
     QUREY_RST qr;
     char sql[256];
     sprintf(sql, "SELECT * FROM orders WHERE buyer_name = '%s';", msg_g.buf);
     querySql(pDB, sql, &qr);

     if (qr.row > 0)
     {
          int jump = qr.col;
          for (size_t i = 0; i < qr.row; i++)
          {
               sc.id = atoi(qr.pzResult[jump + i * jump]);            // 唯一id
               strcpy(sc.selfName, qr.pzResult[jump + i * jump + 1]); // 购买的名字
               strcpy(sc.destName, qr.pzResult[jump + i * jump + 2]); // 卖家名字
               sc.game_id = atoi(qr.pzResult[jump + i * jump + 3]);   // 游戏id
               sc.price = atoi(qr.pzResult[jump + i * jump + 4]);     // 购买价格
               strcpy(sc.time, qr.pzResult[jump + i * jump + 5]);     // 购买时间
               msg.type = queryChatRec;                               // 有订单
               memcpy(msg.buf, &sc, sizeof(SINGLE_CHAT));
               // 把包含有一条聊天记录的消息发送给客户端
               int ret = send(sID, &msg, sizeof(msg), 0);
               if (ret == -1)
               {
                    printf("发送数据出错了\n");
                    break;
               }
          }
          msg.type = queryOver; // 查询结束
          //  把查询的消息发送给客户端
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
     }
     else
     {
          msg.type = no_news; // 没有订单
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
     }
}

int work(int sID, MSG msg)
{
     if (msg.type == regist) // 注册
     {
          // 把缓冲区的类型转为注册
          RGU *pRgu = (RGU *)msg.buf;
          char szSql[512];
          // 把用户名和密码插入到数据表中
          sprintf(szSql, "INSERT INTO users (username, password, phone, birth_date)\
               VALUES ( '%s', '%s' ,'%s', '%s')",
                  pRgu->name, pRgu->pwd, pRgu->phone, pRgu->date);
          char *msg_1 = NULL;
          sqlite3_exec(pDB, szSql, 0, 0, &msg_1);
          // 如果msg不为空，说明有错误信息
          if (msg_1 != NULL)
          {
               sprintf(msg.buf, "注册失败，错误的原因是：%s", msg_1);
          }
          else
          {
               sprintf(msg.buf, "注册成功");
          }
          int ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
     }
     else if (msg.type == login) // 登录
     {
          // 把缓冲区的类型转为注册，因为注册和登录用的是同一个结构体
          RGU *pRgu = (RGU *)msg.buf;

          int ret = 0;
          RGU rgu;
          // 因为登录成功了，所以把消息类型改为ok，再发回去
          msg.type = no;

          char sql[512];
          sprintf(sql, "select * from users where username = '%s' AND password = '%s';", pRgu->name, pRgu->pwd);

          QUREY_RST qr;
          // 执行查询语句
          querySql(pDB, sql, &qr);
          // 如果结果的行数是>0的，说明数据库中有记录，那么登陆成功
          if (qr.row > 0)
          {
               // 因为登录成功了，所以把消息类型改为ok，再发回去
               msg.type = ok;
               // 把登录成功的用户名和地址保存起来
               sprintf(sql, "INSERT INTO user_logins (username, fd)\
               VALUES ( '%s', '%d')",
                       pRgu->name, sID);
               char *msg_1 = NULL;
               sqlite3_exec(pDB, sql, 0, 0, &msg_1);
               if (msg_1 != NULL)
               {
                    printf("存放登录信息失败，错误的原因是：%s", msg_1);
                    msg.type = repe; // 登录信息重复
                    printf("消息类型为：%d\n", msg.type);
                    // 把消息发回客户端，告诉它登录成功了
                    ret = send(sID, &msg, sizeof(msg), 0);
                    if (ret == -1)
                    {
                         printf("发送数据出错了\n");
                    }
                    return 1;
               }
          }

          printf("消息类型为：%d\n", msg.type);
          // 把消息发回客户端，告诉它登录成功了
          ret = send(sID, &msg, sizeof(msg), 0);
          if (ret == -1)
          {
               printf("发送数据出错了\n");
          }
     }
     else if (msg.type == shell) // 单聊
     {
          shellfunc(sID, msg);
     }
     else if (msg.type == singleChat) // 单聊
     {
          singleChat_func(sID, msg);
     }
     else if (msg.type == showgamezhanghao_gamename) // 根据游戏名显示账号
     {
          querygameRecord_gamename(sID, msg);
     }
     else if (msg.type == showgamezhanghao_name) // 根据用户名显示账号
     {
          querygameRecord_name(sID, msg);
     }
     else if (msg.type == showgamezhanghao_all) // 查看所有账号
     {
          querygameRecord_all(sID);
     }
     else if (msg.type == my_account) // 显示自己的账号内容
     {
          myaccount_func(sID, msg);
     }
     else if (msg.type == chat_goumai) // 交流与购买
     {
          chatgoumai(sID, msg);
     }
     else if (msg.type == leave) // 留言
     {
          leavefunc(sID, msg);
     }
     else if (msg.type == user_goumai) // 购买
     {
          goumaifunc(sID, msg);
     }
     else if (msg.type == examine) // 查看几行
     {
          examine_func(sID, msg);
     }
     else if (msg.type == examinelook) // 查看新消息
     {
          examinelook_func(sID, msg);
     }
     else if (msg.type == examinelookall) // 查看聊天记录
     {
          examinelookall_func(sID, msg);
     }
     else if (msg.type == affirm_self) // 看是不是自己的账号
     {
          affirmself(sID, msg);
     }
     else if (msg.type == chat_quit) // 退出聊天
     {
          chatquit(sID, msg);
     }
     else if (msg.type == order) // 查看订单
     {
          orderfunc(sID, msg);
     }
     else if (msg.type == quitall) // 退出账号
     {
          quitall_s(msg);
     }
     else
     {
     }
     return 1;
}

int initDatabase() // 打开数据库
{
     pDB = openSqlite3("abc.db");
     if (pDB == NULL)
     {
          printf("打开或者创建数据库失败\n");
          return -1;
     }
     return 1;
}

int main(int c, char *arg[])
{
     if (initDatabase() == -1)
     {
          return 0;
     }

     struct sockaddr_in sin;
     sin.sin_family = AF_INET;   // IPV4的网络地址版本
     sin.sin_port = htons(9000); // 把9000号端口转为网络字节序并赋值给端口参数

     u_int32_t ip = 0;
     // 把字符串ip地址转为网络字节序ip
     inet_pton(AF_INET, "192.168.80.149", &ip);
     sin.sin_addr.s_addr = ip;

     // 创建一个tcp套接字，参数1指定地址族，参数2指定协议，SOCK_STREAM代表是TCP，SOCK_DGRAM代表UDP
     int sID = socket(AF_INET, SOCK_STREAM, 0);
     // 使端口号马上能被重新使用
     int opt = 1;
     if (setsockopt(sID, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
     {
          perror("设置套接字属性出错");
     }
     // 把套接字和地址绑定（手机+手机号）
     if (-1 == bind(sID, (struct sockaddr *)&sin, sizeof(sin)))
     {
          perror("绑定地址失败，请等待30秒或者换一个端口试试");
          return 0;
     }

     // 打开监听功能，监听绑定地址上的来访请求，5代表同时允许5个客户端排队连接
     listen(sID, 5);

     // 定义MAX_EVENT个事件结构体，每个结构体中都有感兴趣的事件和套接字
     struct epoll_event ev, events[MAX_EVENT];

     // 创建epoll对象
     int epoll_id = epoll_create(MAX_EVENT); // 创建一个可以管理MAX_EVENT个套接字事件的epoll对象

     ev.events = EPOLLIN; // 感兴趣的事件为有数据可读
     ev.data.fd = sID;    // 感兴趣的套接字

     // epoll操作和控制，EPOLL_CTL_ADD是往epoll对象中添加结构体
     // 该函数内部会复制最后的结构体ev，所以ev可以重复使用
     epoll_ctl(epoll_id, EPOLL_CTL_ADD, sID, &ev);

     while (1)
     {
          // count是当前一共有多少个套集字有可读事件
          // 例如如果当前epoll对象中只有一个套接字有可读事件，那么epoll_wait就会把这个套接字的结构体存入events数组中
          // 而且是按顺序存放的，第一个有事件的套机字结构体就是下标为0的元素
          int count = epoll_wait(epoll_id, events, MAX_EVENT, -1);

          if (count == -1)
          {
               perror("epoll_wait");
               return 0;
          }

          for (size_t i = 0; i < count; i++)
          {
               int fd = events[i].data.fd;
               printf("fd = %d\n", fd);
               if (fd == sID) // 说明i是监听套接字
               {
                    printf("因为i(%lu)就是监听套接字，它上面发生的可读事件是说明有用户来连接我们了\n", i);
                    struct sockaddr_in clientAddr;
                    socklen_t len = sizeof(clientAddr);
                    int newFd = accept(fd, (struct sockaddr *)&clientAddr, &len);
                    printf("产生了一个新的套接字，快为它准一个结构体，并加入到epoll对象中管理起来吧\n");
                    ev.data.fd = newFd; // 把新的套接字赋值给结构体
                    // epoll操作和控制，EPOLL_CTL_ADD是往epoll对象中添加结构体
                    if (0 == epoll_ctl(epoll_id, EPOLL_CTL_ADD, newFd, &ev))
                    {
                         printf("套接字加入epoll成功\n");
                    }
               }
               else
               {
                    MSG msg;
                    int ret = read(fd, &msg, sizeof(MSG));
                    if (ret <= 0)
                    {
                         // 把要移除的套接字结构体准备好
                         ev.data.fd = fd;
                         // 把套接字结构体从epoll中移除掉
                         if (0 == epoll_ctl(epoll_id, EPOLL_CTL_DEL, fd, &ev))
                         {
                              printf("从epoll中移除套接字结构体成功\n");
                         }
                         else
                         {
                              perror("epoll");
                              printf("从epoll中移除套接字结构体失败\n");
                         }
                         close(fd);
                         continue; // 指向下一个循环
                    }
                    else
                    {
                         // printf("收到客户端的消息：%s\n", buf);
                         work(fd, msg);
                    }
               }
          }
     }
     close(sID);

     return 0;
}